package com.sqs.interceptor;

import cn.hutool.core.util.StrUtil;
import com.sqs.constant.JwtClaimsConstant;
import com.sqs.constant.ExceptionConstant;
import com.sqs.constant.RedisConstant;
import com.sqs.constant.RequestConstant;
import com.sqs.context.BaseContext;
import com.sqs.exception.BaseException;
import com.sqs.exception.UnauthorizedException;
import com.sqs.properties.JwtProperties;
import com.sqs.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.SignatureException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class JwtTokenUserInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @CrossOrigin
    public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler){
        if(!(handler instanceof HandlerMethod)){
            return true;
        }
        //1.取出token
        String token = request.getHeader(RequestConstant.AUTHORIZATION);
        if(token == null || token.isEmpty()){
            throw new BaseException(ExceptionConstant.CODE_401, ExceptionConstant.NOT_FOUND_JWT);
        }
        //2.校验并解析token
        Long userId = null;
        try{
            Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
            //获取用户信息（假设用户ID存储在"userId"声明中）
            userId = claims.get(JwtClaimsConstant.USER_ID, Long.class);
        }catch (JwtException | IllegalArgumentException e) {
            throw new UnauthorizedException(ExceptionConstant.INVALID_TOKEN);
        } catch (Exception e) {
            throw new UnauthorizedException(ExceptionConstant.NOT_AUTHORIZED);
        }
        BaseContext.setCurrentId(userId);
        //3.判断redis中是否存在该用户的jwt，如果存在就刷新时间
        String jwt = stringRedisTemplate.opsForValue().getAndExpire(RedisConstant.TOKEN_HEAD + userId, RedisConstant.TOKEN_TTL, TimeUnit.MINUTES);
        if(StrUtil.isBlank(jwt) || !jwt.equals(token)){
            throw new UnauthorizedException(ExceptionConstant.TIMEOUT_TOKEN);
        }

        return true;
    }

}
